package com.example.datamanage.utils;

import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.http.ContentType;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.example.datamanage.common.CodeEnum;
import com.example.datamanage.common.FileTypeEnum;
import com.example.datamanage.exception.MyException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author 28142
 * @description 文件导出工具类
 * @date 2023/8/1 16:47
 */
@Component
public class ExportUtils {
    private static Logger logger = LoggerFactory.getLogger(ExportUtils.class);
    /**
     * 导出文件，提取为工具类方法
     * @author 杨雨盛
     * @date 2023/8/1 16:55 
     * @param fileName
     * @param type
     * @param list
     * @param response 
     */
    public void export(String fileName, String type, List<LinkedHashMap<String, Object>> list, HttpServletResponse response) {
        logger.info("正在导出:" + fileName + "." + type + "文件");
        // 根据用户选择导出不同文件类型
        if (FileTypeEnum.XLS.getType().equals(type) || FileTypeEnum.XLSX.getType().equals(type)) {
            exportExcel(list, type, fileName, response);
        } else if (FileTypeEnum.CSV.getType().equals(type)) {
            exportCsv(list, fileName, response);
        } else if (FileTypeEnum.TXT.getType().equals(type)) {
            exportTxt(list, fileName, response);
        } else if (FileTypeEnum.HTML.getType().equals(type)) {
            exportHtml(list, fileName, response);
        } else if (FileTypeEnum.XML.getType().equals(type)) {
            exportXml(list, fileName, response);
        } else if (FileTypeEnum.JSON.getType().equals(type)) {
            exportJson(list, fileName, response);
        }
    }

    /**
     * 导出excel文件
     * @author 杨雨盛
     * @date 2023/7/26 15:49
     * @param list
     * @param response
     */
    public void exportExcel(List<LinkedHashMap<String, Object>> list,
                            String type,
                            String fileName,
                            HttpServletResponse response) {
        try {
            // 在内存操作，写到浏览器
            ExcelWriter writer = ExcelUtil.getWriter(true);
            // 一次性将list内的对象写到excel，使用默认样式
            writer.write(list, true);
            // 设置浏览器响应格式
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + "." + type);
            ServletOutputStream outputStream = response.getOutputStream();
            writer.flush(outputStream, true);
            outputStream.close();
            writer.close();
            logger.info("导出完成，共导出" + list.size() + "条数据");
        } catch (Exception e) {
            logger.error("导出失败：" + e);
            e.printStackTrace();
            throw new MyException(CodeEnum.CODE_503.getCode(), "导出失败");
        }
    }

    /**
     * 导出csv文件
     * @author 杨雨盛
     * @date 2023/7/26 15:49
     * @param list
     * @param response
     */
    public void exportCsv(List<LinkedHashMap<String, Object>> list,
                          String fileName,
                          HttpServletResponse response) {
        try {
            response.setContentType(ContentType.OCTET_STREAM.toString());
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".csv");
            CsvWriter csvWriter = CsvUtil.getWriter(response.getWriter());
            csvWriter.writeBeans(list);
            csvWriter.close();
            logger.info("导出完成，共导出" + list.size() + "条数据");
        } catch (Exception e) {
            logger.error("导出失败：" + e);
            throw new MyException(CodeEnum.CODE_503.getCode(), "导出失败");
        }
    }

    /**
     * 导出txt文件
     * @author 杨雨盛
     * @date 2023/7/30 19:05
     * @param list
     * @param response
     */
    public void exportTxt(List<LinkedHashMap<String, Object>> list,
                          String fileName,
                          HttpServletResponse response) {
        try {
            response.setContentType(ContentType.TEXT_PLAIN.toString());
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".txt");

            BufferedOutputStream buff = new BufferedOutputStream(response.getOutputStream());
            // StringBuffer字符串
            StringBuffer write = new StringBuffer();
            boolean flag = true;
            // 以tab分隔会有问题，有些是四个空格，有些是一个空格，因此直接写了个分隔的字符串
            String space = "        ";
            for (LinkedHashMap<String, Object> map : list) {
                // 打印表头
                if (flag) {
                    for (String s : map.keySet()) {
                        write.append(s + space);
                    }
                    write.append("\n");
                    flag = false;
                }
                // 遍历获取字段值
                for (Object value : map.values()) {
                    write.append(value + space);
                }
                write.append("\n");
            }
            buff.write(write.toString().getBytes("UTF-8"));
            buff.flush();
            buff.close();
            logger.info("导出完成，共导出" + list.size() + "条数据");
        } catch (Exception e) {
            logger.error("导出失败：" + e);
            throw new MyException(CodeEnum.CODE_503.getCode(), "导出失败");
        }
    }

    /**
     * 导出html文件
     * @author 杨雨盛
     * @date 2023/7/30 19:05
     * @param list
     */
    public void exportHtml(List<LinkedHashMap<String, Object>> list,
                           String fileName,
                           HttpServletResponse response) {
        try {
            // 设置响应头，指定文件名为 "导出结果.html"
            response.setContentType(ContentType.TEXT_HTML.toString());
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".html");

            StringBuilder builder = new StringBuilder();
            // 开始 HTML 表格
            builder.append("<table border=\"1\">");
            // 表头
            builder.append("<tr>");
            for (String key : list.get(0).keySet()) {
                builder.append("<th>").append(key).append("</th>");
            }
            builder.append("</tr>");
            // 表格内容
            for (LinkedHashMap<String, Object> row : list) {
                builder.append("<tr>");
                for (Object value : row.values()) {
                    builder.append("<td>").append(value).append("</td>");
                }
                builder.append("</tr>");
            }
            // 结束 HTML 表格
            builder.append("</table>");

            // 将 JSON 数据写入响应输出流
            PrintWriter writer = response.getWriter();
            writer.write(builder.toString());
            writer.flush();
            writer.close();
            logger.info("导出完成，共导出" + list.size() + "条数据");
        } catch (IOException e) {
            e.printStackTrace();
        }
        /* try {
            // 创建文件对象
            File file = new File("导出结果.html");
            // 创建文件写入流
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            StringBuilder builder = new StringBuilder();

            // 开始 HTML 表格
            builder.append("<table border=\"1\">");
            // 表头
            builder.append("<tr>");
            for (String key : list.get(0).keySet()) {
                builder.append("<th>").append(key).append("</th>");
            }
            builder.append("</tr>");
            // 表格内容
            for (LinkedHashMap<String, Object> row : list) {
                builder.append("<tr>");
                for (Object value : row.values()) {
                    builder.append("<td>").append(value).append("</td>");
                }
                builder.append("</tr>");
            }
            // 结束 HTML 表格
            builder.append("</table>");

            // 写入html内容到文件
            bufferedWriter.write(builder.toString());

            // 关闭流
            bufferedWriter.close();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw new MyException(CodeEnum.CODE_503.getCode(), "导出失败");
        } */
    }


    /**
     * 导出json文件
     * @author 杨雨盛
     * @date 2023/7/30 19:08
     * @param list
     */
    public void exportJson(List<LinkedHashMap<String, Object>> list,
                           String fileName,
                           HttpServletResponse response) {
        try {
            // 设置响应头，指定文件名为 "导出结果.json"
            response.setContentType(ContentType.JSON.toString());
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".json");

            // 将对象转换为 JSON 字符串
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonString = objectMapper.writeValueAsString(list);

            // 将 JSON 数据写入响应输出流
            PrintWriter writer = response.getWriter();
            writer.write(jsonString);
            writer.flush();
            writer.close();
            logger.info("导出完成，共导出" + list.size() + "条数据");
        } catch (IOException e) {
            logger.error("导出失败：" + e);
            e.printStackTrace();
        }
        /* try {
            // 创建文件对象
            File file = new File("导出结果.json");

            // 创建文件写入流
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

            // 将对象转换为 JSON 字符串
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonString = objectMapper.writeValueAsString(list);

            // 写入 JSON 内容到文件
            bufferedWriter.write(jsonString);

            // 关闭文件写入流
            bufferedWriter.close();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw new MyException(CodeEnum.CODE_503.getCode(), "导出失败");
        } */
    }

    /**
     * 导出xml文件
     * @author 杨雨盛
     * @date 2023/7/30 19:19
     * @param list
     */
    public void exportXml(List<LinkedHashMap<String, Object>> list,
                          String fileName,
                          HttpServletResponse response) {
        try {
            // 设置响应头，指定文件名为 "导出结果.xml"
            response.setContentType(ContentType.XML.toString());
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xml");

            // 将对象转换为 XML 字符串
            XmlMapper xmlMapper = new XmlMapper();
            String xmlString = xmlMapper.writeValueAsString(list);

            // 将 JSON 数据写入响应输出流
            PrintWriter writer = response.getWriter();
            writer.write(xmlString);
            writer.flush();
            writer.close();
            logger.info("导出完成，共导出" + list.size() + "条数据");
        } catch (IOException e) {
            logger.error("导出失败：" + e);
            e.printStackTrace();
        }
        /* try {
            // 创建文件对象
            File file = new File("导出结果.xml");

            // 创建文件写入流
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

            // 将对象转换为 XML 字符串
            XmlMapper xmlMapper = new XmlMapper();
            String xmlString = xmlMapper.writeValueAsString(list);

            // 写入 XML 内容到文件
            bufferedWriter.write(xmlString);

            // 关闭文件写入流
            bufferedWriter.close();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            // 处理导出失败的情况
            System.out.println("XML 文件导出失败：" + e.getMessage());
        } */
    }
}
